#ifndef __DiffMuscle1_h__
#define __DiffMuscle1_h__

//#include <OpenSim/Actuators/osimActuatorsDLL.h>
#include <OpenSim/Common/PropertyObjPtr.h>
#include <OpenSim/Simulation/Model/ActivationFiberLengthMuscle.h>
#include "osimPluginDLL.h"


#ifdef SWIG

	#ifdef OSIMACTUATORS_API

		#undef OSIMACTUATORS_API

		#define OSIMACTUATORS_API

	#endif

#endif



namespace OpenSim {

class OSIMPLUGIN_API DiffMuscle1 :
	public ActivationFiberLengthMuscle
{
protected:
	static const std::string STATE_SLOW_ACTIVATION_NAME;
	
	
//=============================================================================
// METHODS
//=============================================================================
	//--------------------------------------------------------------------------
	// CONSTRUCTION
	//--------------------------------------------------------------------------
public:
	DiffMuscle1();
	DiffMuscle1(const std::string &aName,double aMaxIsometricForce,double aOptimalFiberLength,double aTendonSlackLength,double aPennationAngle);
	DiffMuscle1(const DiffMuscle1 &aMuscle);
	virtual ~DiffMuscle1();
	virtual Object* copy() const;

#ifndef SWIG
	DiffMuscle1& operator=(const DiffMuscle1 &aMuscle);
#endif
	void copyData(const DiffMuscle1 &aMuscle);

#ifndef SWIG

#endif

	//--------------------------------------------------------------------------
	// GET
	//--------------------------------------------------------------------------
	// Properties
	virtual double getVmax0FastFiber() const { return getPropertyValue<double>("Vmax0FastFiber"); }
	virtual double getVmax0SlowFiber() const { return getPropertyValue<double>("Vmax0SlowFiber"); }
	virtual double getAfFastFiber() const { return getPropertyValue<double>("AfFastFiber"); }
	virtual double getAfSlowFiber() const { return getPropertyValue<double>("AfSlowFiber"); }
	virtual double getFlen() const { return getPropertyValue<double>("Flen"); }
	virtual double getScaleFastFiber() const { return getPropertyValue<double>("ScaleFastFiber"); }
	virtual double getScaleSlowFiber() const { return getPropertyValue<double>("ScaleSlowFiber"); }
	virtual Function* getActiveForceLengthCurve() const;
	virtual Function* getPassiveForceLengthCurve() const;
	
	virtual bool setVmax0FastFiber( double Vmax0 );
	virtual bool setVmax0SlowFiber( double Vmax0 );
	virtual bool setAfFastFiber( double aAf );
	virtual bool setAfSlowFiber( double aAf );
	virtual bool setFlen( double aFlen);
	virtual bool setScaleFastFiber( double cFastFiber);
	virtual bool setScaleSlowFiber( double cSlowFiber);
	virtual bool setActiveForceLengthCurve(Function* aActiveForceLengthCurve);
	virtual bool setPassiveForceLengthCurve(Function* aPassiveForceLengthCurve);

	// Computed quantities
#ifndef SWIG

	//--------------------------------------------------------------------------
	// FORCE-LENGTH-VELOCITY PROPERTIES
	//--------------------------------------------------------------------------

	//--------------------------------------------------------------------------
	// COMPUTATIONS
	//--------------------------------------------------------------------------
	virtual double computeActuation(const SimTK::State& s) const;
	double calcTendonForce(const SimTK::State& s, double aNormTendonLength) const;
	double calcPassiveForce(const SimTK::State& s, double aNormFiberLength) const;
	double calcActiveForceFastFiber(const SimTK::State& s, double aNormFiberLength) const;
	double calcActiveForceSlowFiber(const SimTK::State& s, double aNormFiberLength) const;
	double calcActiveForce(const SimTK::State& s, double aNormFiberLength) const;
	double calcFiberVelocity(const SimTK::State& s, double aActivation, double aActiveForce, double aVelocityDependentForce) const;
	virtual double computeIsometricForce(SimTK::State& s, double activation) const;

#endif
	virtual int getStateVariableYIndex(int index) const;

	OPENSIM_DECLARE_DERIVED(DiffMuscle1, ActivationFiberLengthMuscle);

protected:
	/** calculate muscle's position related values such fiber and tendon lengths,
	normalized lengths, pennation angle, etc... */
	virtual void calcMuscleLengthInfo(const SimTK::State& s, MuscleLengthInfo& mli) const;

	/** calculate muscle's velocity related values such fiber and tendon velocities,
		normalized velocities, pennation angular velocity, etc... */
	virtual void  calcFiberVelocityInfo(const SimTK::State& s, FiberVelocityInfo& fvi) const;

	/** calculate muscle's active and passive force-length, force-velocity, 
	    tendon force, relationships and their related values */
	virtual void  calcMuscleDynamicsInfo(const SimTK::State& s, MuscleDynamicsInfo& mdi) const;

	/** Calculate activation rate */
	virtual double calcActivationRate(const SimTK::State& s) const;

private:
	void setNull();
	void setupProperties();
//=============================================================================
};	// END of class DiffMuscle
//=============================================================================
} // end of namespace OpenSim
#endif // __DiffMuscle1_h__